#include "biplTypes.h"
#include <sstream>

/// implicitly convert to bool
degreeTypes::operator bool() const
{
	if (val == 0.0f)
		return false;
	else
		return true;
}

/// implicitly convert to other types
degreeTypes::operator pairTypes() const
{
	return toPair();
}

degreeTypes::operator stringTypes() const
{
	return toString();
}

/// output stream operator
std::ostream&
	operator<<(std::ostream&out, const degreeTypes& s)
{
	out << s.toString();
	return out;
}

/// Negation Operator
degreeTypes operator- (const degreeTypes &s)
{
	return degreeTypes(-s.val);
}

/// Arithmetic Operators
const degreeTypes operator+(const degreeTypes& lhs, const degreeTypes& rhs)
{
	return degreeTypes(lhs.val + rhs.val);
}

const degreeTypes operator-(const degreeTypes& lhs, const degreeTypes& rhs)
{
	return degreeTypes(lhs.val - rhs.val);
}

const degreeTypes operator/(const degreeTypes& lhs, const degreeTypes& rhs)
{
	return degreeTypes(lhs.val / rhs.val);
}

const degreeTypes operator*(const degreeTypes& lhs, const degreeTypes& rhs)
{
	return degreeTypes(lhs.val * rhs.val);
}

const degreeTypes operator%(const degreeTypes& lhs, const degreeTypes& rhs)
{
	return degreeTypes(fmod(lhs.val, rhs.val));
}

/// Arithmetic Assignment Operators
degreeTypes& operator+=(degreeTypes& lhs, const degreeTypes& rhs)
{
	lhs.val += rhs.val;
	return lhs;
}

degreeTypes& operator-=(degreeTypes& lhs, const degreeTypes& rhs)
{
	lhs.val -= rhs.val;
	return lhs;
}

degreeTypes& operator*=(degreeTypes& lhs, const degreeTypes& rhs)
{
	lhs.val *= rhs.val;
	return lhs;
}

degreeTypes& operator/=(degreeTypes& lhs, const degreeTypes& rhs)
{
	lhs.val /= rhs.val;
	return lhs;
}

degreeTypes& operator%=(degreeTypes& lhs, const degreeTypes& rhs)
{
	lhs.val = fmod(lhs.val, rhs.val);
	return lhs;
}

/// Equality Operators
boolTypes operator==(const boolTypes& left, const degreeTypes& right)
{
	return boolTypes(left == right.toBoolean());
}

boolTypes operator!=(const boolTypes& left, const degreeTypes& right)
{
	return boolTypes(left == right.toBoolean());
}

boolTypes operator==(const degreeTypes& left, const boolTypes& right)
{
	return boolTypes(left.toBoolean() == right);
}

boolTypes operator!=(const degreeTypes& left, const boolTypes& right)
{
	return boolTypes(left.toBoolean() == right);
}

boolTypes operator==(const degreeTypes& left, const degreeTypes& right)
{
	return boolTypes(left.val == right.val);
}

boolTypes operator!=(const degreeTypes& left, const degreeTypes& right)
{
	return boolTypes(left.val == right.val);
}

/// Logical Operators
boolTypes operator!(const degreeTypes& s)
{
	return !s.toBoolean();
}

boolTypes operator&&(const degreeTypes& left, const degreeTypes& right)
{
	return left.toBoolean() && right.toBoolean();
}

boolTypes operator||(const degreeTypes& left, const degreeTypes& right)
{
	return left.toBoolean() || right.toBoolean();
}

/// Type conversion functions
boolTypes degreeTypes::toBoolean() const
{
	if (val == 0.0f)
		return boolTypes(false);
	else
		return boolTypes(true);
}

intTypes degreeTypes::toInteger() const
{
	return intTypes(int(val));
}

floatTypes degreeTypes::toFloat() const
{
	return floatTypes(val);
}

degreeTypes degreeTypes::toDegree() const
{
	return degreeTypes(val);
}

pairTypes degreeTypes::toPair() const
{
	return pairTypes(val, val);
}

stringTypes degreeTypes::toString() const
{
	std::stringstream ss(std::stringstream::in | std::stringstream::out);
	ss << '[' << val << ']';
	return stringTypes(ss.str());
}
